ci: fix silently-broken SBOM attestation in release workflow#201
Conversation
The attest job's SBOM steps all carried continue-on-error, so the job reported success while producing no SBOM. Root cause: `cyclonedx-py requirements` was invoked with no input file (this is a uv project, no requirements.txt), so python-sbom.cdx.json was never created, the merge `cp` fallback failed, and attest-sbom hit ENOENT. Second latent bug: actions/checkout deletes the workspace (including the downloaded dist/), so the post-checkout attest-sbom subject-path would have found nothing even if the SBOM had been generated. Replace the cyclonedx-py + cargo-sbom + cyclonedx-cli merge pipeline with a single anchore/sbom-action (syft) pass that catalogs both uv.lock and Cargo.lock statically. syft never executes Cargo/build code to enumerate packages, which is the correct posture for a supply-chain security product. Check source into ./source so dist/ survives for attestation. Drop continue-on-error so a missing SBOM gates publish rather than shipping silently. Build provenance was unaffected (runs before checkout, never continue-on-error); PyPI publish and the weekly attestation health check both verify provenance only, which is why this went unnoticed.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Run ID: 📒 Files selected for processing (1)
WalkthroughThe ChangesSBOM Pipeline Replacement and Attestation Hardening
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.github/workflows/release-please.yml:
- Around line 250-253: The actions/checkout step is persisting credentials
unnecessarily, which exposes the job token to subsequent third-party action
execution. Add persist-credentials: false to the with section of the
actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd action, after the
existing ref and path parameters, to prevent the git credentials from being
written to the git config file in the source directory.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro
Run ID: 10eba78d-f089-4d8b-9732-3dd6c5414be5
📒 Files selected for processing (1)
.github/workflows/release-please.yml
Security review of #201 found the SBOM was generated correctly but with hardening gaps. Apply all four findings: (1) isolate syft (third-party) into a credential-less 'sbom' job so the OIDC signing token in 'attest' is never exposed to untrusted code; (2) exclude tests/** via .github/syft.yaml so the BOM describes shipped deps, not the test harness (syft was cataloging tests/integration/saas/requirements.txt); (3) jq guard fails closed on a valid-but-empty SBOM; (4) disable the action's upload-artifact/upload-release-assets side-effects, handing the SBOM to attest via an explicit artifact. Also gate publish on needs.attest.result=='success': required now that attest is *skipped* (not failed) when sbom fails, which a plain !failure() check would let publish through unattested.
Problem
The release workflow's
attestjob has been reporting ✓ green on every release while producing no SBOM attestation at all. Discovered chasing the v0.11.0 release (run 27888587683): the job is green but its annotations showENOENT: sbom.cdx.jsonplus threeexit code 1/2failures — all swallowed bycontinue-on-error: trueon every SBOM step.Note
0.11.0 itself is fine. It published correctly and has a valid build-provenance attestation (that step runs before checkout and was never
continue-on-error). PyPI publish and the weeklyattestation-check.ymlboth verify provenance only, which is exactly why the missing SBOM went unnoticed. This is fix-forward — 0.11.0 is not being backfilled.Root cause (two bugs)
cyclonedx-py requirementshad no input file. This is a uv project (uv.lock, norequirements.txt), so therequirementssubcommand exits non-zero →python-sbom.cdx.jsonis never created → the merge step'scpfallback fails →sbom.cdx.jsonnever exists →attest-sbomhitsENOENT.actions/checkoutdestroysdist/. The job log showsDeleting the contents of '.../cachekit-py'— checkout wipes the whole workspace (including the downloaded wheels/sdist) before cloning. So the post-checkoutattest-sbomstep'ssubject-path: dist/*would have found nothing even if the SBOM had been generated.Every step's
continue-on-error: truehid both failures behind a green check (violates the "no silent failures" rule).Fix
cyclonedx-py+cargo-sbom+cyclonedx-cli mergepipeline with oneanchore/sbom-action(syft) pass that catalogs bothuv.lock(Python) andCargo.lock(Rust). Verified syft registersnewUvLockParserfor**/uv.lockand parsesCargo.lockstatically — it never executes Cargo/build.rs/proc-macros to enumerate deps, unlikecargo-sbom. For a supply-chain security product, generating the SBOM without executing untrusted build code is the correct posture../sourcesoactions/checkoutonly wipes that subdir, leavingdist/at the workspace root for attestation.continue-on-errorso a missing SBOM gates publish (publishneeds: attest) instead of shipping silently. Releases remain re-runnable viaworkflow_dispatch.Net −11 lines (fewer moving parts than before).
actionlintclean.Type
ci:— workflow config only. The published library is byte-identical; this must not cut a release.Verification
actionlint .github/workflows/release-please.yml→ cleanuv.lock+Cargo.lockcataloger support confirmed in sourcedist/reproduced in the real run logworkflow_dispatchdry run) — by design the SBOM path only runs on release.Summary by CodeRabbit